package map;

/**
 * The Map class represents the game board. It holds an array of Tile objects, and provides methods
 * for converting between rectangular (x, y) and hexagonal (a, b, c) coordinates. Additionally, it
 * provides all the ways to get information about where Tiles are, pathfinding between tiles, field
 * of view.
 * 
 * @author Kyle_Solo
 */
public class Map {
	/**
	 * @author Kyle_Solo
	 */

	public enum DIRECTION {
		/**
		 * East
		 */
		E,
		/**
		 * North
		 */
		N,
		/**
		 * Northeast
		 */
		NE,
		/**
		 * Northwest
		 */
		NW,
		/**
		 * South
		 */
		S,
		/**
		 * Southeast
		 */
		SE,
		/**
		 * Southwest
		 */
		SW,
		/**
		 * West
		 */
		W
	}

	/**
	 * Converts between rectangular and hexagonal coordinates
	 * 
	 * @param x
	 * @param y
	 * @return a
	 */
	public static int getA(int x, int y) {
		if (y % 2 == 0) {
			return 2 * x;
		} else {
			return 2 * x + 1;
		}
	}

	/**
	 * Converts between rectangular and hexagonal coordinates
	 * 
	 * @param x
	 * @param y
	 * @return b
	 */
	public static int getB(int x, int y) {
		if (y % 2 == 0) {
			return y / 2 - x;
		} else {
			return (y - 1) / 2 - x;
		}
	}

	/**
	 * Converts between rectangular and hexagonal coordinates
	 * 
	 * @param x
	 * @param y
	 * @return c
	 */
	public static int getC(int x, int y) {
		return -getA(x, y) - getB(x, y);
	}

	/**
	 * Converts between hexagonal and rectangular coordinates
	 * 
	 * @param a
	 * @param b
	 * @param c
	 * @return x
	 */
	static int getX(int a, int b, int c) {
		if (a >= 0) {
			return a / 2;
		} else {
			return a / 2 - 1;
		}
	}

	/**
	 * Converts between hexagonal and rectangular coordinates
	 * 
	 * @param a
	 * @param b
	 * @param c
	 * @return y
	 */
	static int getY(int a, int b, int c) {
		return a + 2 * b;
	}

	private Tile map[][];

	/**
	 * Creates a new Map, with width*height Tiles.
	 * 
	 * @param width
	 *            the width in Tiles
	 * @param height
	 *            the height in Tiles
	 */
	public Map(int width, int height) {
		map = new Tile[width][height];
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				map[x][y] = new Tile(this, x, y);
			}
		}
	}

	/**
	 * @param x
	 * @param y
	 * @return true if this Map contains a Tile at (x, y)
	 */
	public boolean contains(int x, int y) {
		return (x >= 0 && y >= 0 && x < map.length && y < map[0].length && map[x][y] != null);
	}

	/**
	 * @param a
	 * @param b
	 * @param c
	 * @return true if this Map contains a Tile at (a, b, c)
	 */
	public boolean contains(int a, int b, int c) {
		return contains(getX(a, b, c), getY(a, b, c));
	}

	/**
	 * @param x
	 * @param y
	 * @return the tile at (x, y) or null if there is no tile
	 */
	public Tile getTile(int x, int y) {
		if (contains(x, y)) {
			return map[x][y];
		} else {
			return null;
		}
	}

	/**
	 * @param a
	 * @param b
	 * @param c
	 * @return the tile at (a, b, c) or null if there is no tile
	 */
	public Tile getTile(int a, int b, int c) {
		return getTile(getX(a, b, c), getY(a, b, c));
	}
}
